unit RaListBox;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics, Types, Windows;

type
  TCustomRaListBox = class(TCustomListBox)
    procedure lstDrawItem(Control: TWinControl; Index: integer;
      Rect: TRect; State: TOwnerDrawState);
  private
    FTextColor: TColor;
    FBackColor: TColor;
    FItemBackColor: TColor;
    FItemFrameColor: TColor;
    FSelectedBackColor: TColor;
    FSelectedTextColor: TColor;
    FImages: TImageList;
    function GetSelectedList: TStrings;
  protected
    property BackColor: TColor Read FBackColor Write FBackColor;
    property TextColor: TColor Read FTextColor Write FTextColor;
    property ItemBackColor: TColor Read FItemBackColor Write FItemBackColor;
    property ItemFrameColor: TColor Read FItemFrameColor Write FItemFrameColor;
    property SelectedBackColor: TColor Read FSelectedBackColor Write FSelectedBackColor;
    property SelectedTextColor: TColor Read FSelectedTextColor Write FSelectedTextColor;
    property Images: TImageList Read FImages Write FImages;
  public
    property SelectedList: TStrings Read GetSelectedList;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  TRaListBox = class(TCustomRaListBox)
  private
    FHelp: string;
  published
    property Help: string Read FHelp Write FHelp;
    property AutoComplete;
    // property AutoCompleteDelay;
    property Align;
    property Anchors;
    property BackColor default clWhite;
    property TextColor default clBlack;
    property ItemBackColor default TColor($00FFF7F7);
    property ItemFrameColor default TColor($00131315);
    property SelectedBackColor default TColor($00FFB2B5);
    property SelectedTextColor default clBlue;
    property Color;
    property Images;
    property BevelEdges;
    property BevelInner;
    property BevelKind default bkNone;
    property BevelOuter;
    property BevelWidth;
    property BiDiMode;
    property BorderStyle;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property ExtendedSelect;
    property Font;
    property ImeMode;
    property ImeName;
    property IntegralHeight;
    property ItemHeight default 50;
    property Items;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ScrollWidth;
    property ShowHint;
    property Sorted;
    property TabOrder;
    property TabStop;
    property TabWidth;
    property Visible;
    property OnClick;
    property OnContextPopup;
    property OnData;
    property OnDataFind;
    property OnDataObject;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMeasureItem;
    // property OnMouseActivate;
    property OnMouseDown;
    // property OnMouseEnter;
    // property OnMouseLeave;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;
  end;

function SplitString(Source, Deli: string): TStringList;

implementation

{ TCustomRaListBox }

constructor TCustomRaListBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Style             := lbOwnerDrawFixed;
  Ctl3D             := False;
  ItemHeight        := 50;
  BackColor         := clWhite;
  Color             := BackColor;
  TextColor         := clBlack;
  ItemBackColor     := TColor($00FFF7F7);
  ItemFrameColor    := TColor($00131315);
  SelectedBackColor := TColor($00FFB2B5);
  SelectedTextColor := clBlue;
  OnDrawItem        := lstDrawItem;
  FImages           := nil;
end;

destructor TCustomRaListBox.Destroy;
begin
  FImages := nil;
  inherited Destroy;
end;

function TCustomRaListBox.GetSelectedList: TStrings;
begin

  Result := nil;
  if (Items.Count > 0) and (ItemIndex > -1) then
  begin
    Result := SplitString(Items[ItemIndex], '\n');
  end;
end;

procedure TCustomRaListBox.lstDrawItem(Control: TWinControl; Index: integer;
  Rect: TRect; State: TOwnerDrawState);
var
  subList:       TStringList;
  useImage:      boolean;
  itemLeft:      integer;
  subItemHeight: integer;
  i:             integer;
begin
  Canvas.Brush.Color := BackColor;
  Canvas.Font.Color  := TextColor;
  Canvas.FillRect(Rect);
  Canvas.Brush.Color := ItemBackColor;
  Canvas.Pen.Color   := ItemFrameColor;
  Canvas.RoundRect(Rect.Left + 3, Rect.Top + 3,
    Rect.Right - 2, Rect.Bottom - 2, 8, 8);
  Canvas.RoundRect(Rect.Left + 3, Rect.Top + 3,
    Rect.Right - 3, Rect.Bottom - 3, 5, 5);
  if (odSelected in State) then
  begin
    Canvas.Brush.Color := SelectedBackColor;
    Canvas.RoundRect(Rect.Left + 3, Rect.Top + 3,
      Rect.Right - 3, Rect.Bottom - 3, 5, 5);
    Canvas.Font.Color := SelectedTextColor;
    if (odFocused in State) then
      DrawFocusRect(Canvas.Handle, Rect);
  end;
  if Images = nil then
    useImage := False
  else
    useImage := True;
  if useImage then
    Images.Draw(
      Canvas,
      Rect.Left + 7,
      Rect.top + (ItemHeight - Images.Height) div 2,
      Index);
  subList := SplitString(Items[index], '\n');
  if useImage then
    itemLeft := Rect.Left + 32 + 10
  else
    itemLeft := Rect.Left + 10;
  subItemHeight := (ItemHeight - 8) div subList.Count;
  for i := 0 to subList.Count - 1 do
  begin
    Canvas.TextOut(itemLeft, rect.Top + 4 + (i * subItemHeight),
      subList[i]);
  end;
end;

function SplitString(Source, Deli: string): TStringList;
var
  EndOfCurrentString: byte;
  StringList:         TStringList;
begin
  StringList := TStringList.Create;
  while Pos(Deli, Source) > 0 do
  begin
    EndOfCurrentString := Pos(Deli, Source);
    StringList.add(Copy(Source, 1, EndOfCurrentString - 1));
    Source := Copy(Source, EndOfCurrentString + length(Deli),
      length(Source) - EndOfCurrentString);
  end;
  Result := StringList;
  StringList.Add(Source);
end;

end.
